package org.swift.mashup.engine.model;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.swift.mashup.engine.concurrency.agenda.Action;
import org.swift.mashup.engine.concurrency.memory.MemoryItem;


public class GrabActionTemplate extends BaseActionTemplate {

	private ParameterProcessor paramProcessor;
	private boolean publish;
	
	public GrabActionTemplate(String name, From from, Activity activity, 
			Map<String, With> withs, ParameterProcessor paramProcessor, Collection<When> whens, 
			Map<String, Constant> constants, String encoding) {
		this(name,from, activity, withs, paramProcessor, whens, constants, encoding, false);	
	}
	
	public GrabActionTemplate(String name, From from, Activity activity, 
			Map<String, With> withs, ParameterProcessor paramProcessor, Collection<When> whens, 
			Map<String, Constant> constants, String encoding, boolean isPublish) {
		super(name,from, activity, withs, whens, constants, encoding);
		this.paramProcessor = paramProcessor;
		setPublish(isPublish);
	}

	public Action newAction(Map<String, ?> params) {
		Map<String, Object> withMap = new HashMap<String, Object>();
		withMap.putAll(mergeMaps(this.getWiths(), getMemoryItemValues(params)));	
		withMap.putAll(Parameter.toValueMap(this.getConstants().values()));
        return new Grab(this.getName(), from, activity, withMap, getSendParameters(params),this.getEncoding(),this.getMashupName());
	}
	
	protected Map<String,? extends Object> getSendParameters(Map<String,?> withs){
		return this.paramProcessor.extractParameters(withs);
	}
	
	private Map<String,Object> getMemoryItemValues (Map<String,?> memoryItems){
		Map<String,Object> values = new HashMap<String,Object>();
		for (Entry<String, ? extends Object> entry : memoryItems.entrySet()){
			Object value = entry.getValue();
			if (value instanceof MemoryItem){
				values.put(entry.getKey(), ((MemoryItem)value).toString());				
			}else{
				values.put(entry.getKey(), value);
			}			
		}
		return values;
	}

	/**
	 * Merges the values and keys into one map keymap valueMap A => B B => C
	 * becomes: A => C
	 * 
	 * @param keyMap
	 * @param valueMap
	 * @return
	 */
	private static Map<String, Object> mergeMaps(Map<String, ? extends Parameter> keyMap,
			Map<String, ?> valueMap) {
		Map<String, Object> localMap = new HashMap<String, Object>();
		for (String key : keyMap.keySet()) {
			String valueKey = keyMap.get(key).getValue();
			localMap.put(key, valueMap.get(valueKey));
		}
		return localMap;
	}
	
	public From getFrom() {
		return from;
	}

	public boolean isPublish() {
		return publish;
	}

	public void setPublish(boolean publish) {
		this.publish = publish;
	}
}
